import platgo as pg
import numpy as np


class CF1(pg.Problem):

    def __init__(self, D: int = 10) -> None:
        self.name = "CF1"
        self.type['multi'], self.type['real'], self.type['constrained'], self.type['large'] = [True] * 4
        self.M = 2
        self.D = D
        lb = [0] * self.D
        ub = [1] * self.D
        self.borders = np.array([lb, ub])
        super().__init__()

    def cal_obj(self, pop) -> None:
        j1 = np.arange(2, self.D, 2)
        j2 = np.arange(1, self.D, 2)
        objv1 = pop.decs[:, 0] + 2 * np.mean((pop.decs[:, j1] - pop.decs[:, 0].reshape(-1, 1) ** (0.5 * (1 + 3 * (j1 - 1) / (5 - 2)))) ** 2, axis=1)
        objv2 = 1 - pop.decs[:, 0] + 2 * np.mean((pop.decs[:, j2] - pop.decs[:, 0].reshape(-1, 1) ** (0.5 * (1 + 3 * (j2 - 1) / (5 - 2)))) ** 2, axis=1)
        pop.objv = np.array([objv1, objv2]).T

    def cal_cv(self, pop) -> None:
        pop.cv = (1 - pop.objv[:, 0] - pop.objv[:, 1] +
                  np.abs(np.sin(10 * np.pi * (pop.objv[:, 0]-pop.objv[:, 1] + 1)))).reshape(-1, 1)

    def get_optimal(self) -> np.ndarray:
        ObjV1 = np.arange(0, 1, 1/20)
        ObjV2 = 1 - ObjV1
        referenceObjV = np.array([ObjV1, ObjV2]).T
        return referenceObjV
